<?php

namespace pmvc\data\transform;

use UnexpectedValueException;

/**
 * Utilities for {@link Transformer}s.
 */
abstract class TransformUtil {

	/**
	 * Chains multiple transformers together to 
	 * create a single transformer.  An array of
	 * transformers can be passed to this function
	 * or this function can be used in a varargs
	 * manner.
	 */
	public static function chainTransformer() {
		$args = func_get_args();
		if (count($args)==1 && is_array($args[0])) {
			$args = $args[0];
		}
		return new ClosureTransformer(function($input)use($args) {
			foreach ($args as $transformer) {
				$input = $transformer->transform($input);
			}
			return $input;
		});
	}

	/**
	 * @return Transformer
	 */
	public static function defaultValueTransformer($defaultValue) {
		return new ClosureTransformer(function($input){
			return (isset($input) && $input!='') ? $input : $defaultValue;
		});
	}

	/**
	 * @return Transformer
	 */
	public static function explodeTransformer($delimiter, Transformer $valueTransformer) {
		return new ClosureTransformer(function($input)use($delimiter, $valueTransformer) {
			$output = Array();
			if (isset($input) && !empty($input)) {
				$pieces = explode($delimiter, $input);
				foreach ($pieces as $piece) {
					$output[] = $valueTransformer->transform($piece);
				}
			}
			return $output;
		});
	}

	/**
	 * @return Transformer
	 */
	public static function foreachTransformer(Transformer $valueTransformer) {
		return new ClosureTransformer(function($input)use($valueTransformer) {
			$output = Array();
			foreach ($input as $value) {
				$output[] = $valueTransformer->transform($value);
			}
			return $output;
		});
	}

	/**
	 * @return Transformer
	 */
	public static function objectPropertyTransformer($propertyName) {
		return new ClosureTransformer(function($input)use($propertyName) {
			if (!is_object($input)) {
				throw new UnexpectedValueException("Input is not an object");
			}
			return $input->$propertyName;
		});
	}

	/**
	 * @return Transformer
	 */
	public static function noOpTransformer() {
		return new ClosureTransformer(function($input) {
			return $input;
		});
	}

	/**
	 * @return Transformer
	 */
	public static function regexReplaceTransformer($regex, $replacement) {
		return new ClosureTransformer(function($input)use($regex, $replacement) {
			return preg_replace($regex, $replacement, $input);
		});
	}

	/**
	 * @return Transformer
	 */
	public static function booleanTransformer(
		$trueValues=Array(1, "true", "TRUE", "True", "yes", "YES", "Yes"),
		$falsevalues=Array(0, "false", "FALSE", "False", "no", "NO", "No")) {
		return new ClosureTransformer(function($input)use($trueValues, $falseValues) {
			if (in_array($input, $trueValues, true)) {
				return true;
			}
			if (in_array($input, $falseValues, true)) {
				return false;
			}
			throw new UnexpectedValueException();
		});
	}

	/**
	 * @return Transformer
	 */
	public static function dateTimeTransformer() {
		return new ClosureTransformer(function($input){
			return new DateTime($input);
		});
	}

	/**
	 * @return Transformer
	 */
	public static function integerTransformer() {
		return new ClosureTransformer(function($input){
			if (!is_numeric($input)) {
				throw new UnexpectedValueException("Input is not numeric");
			}
			return intval($input);
		});
	}

	/**
	 * @return Transformer
	 */
	public static function floatTransformer() {
		return new ClosureTransformer(function($input){
			if (!is_numeric($input)) {
				throw new UnexpectedValueException("Input is not numeric");
			}
			return floatval($input);
		});
	}

	/**
	 * @return Transformer
	 */
	public static function stringTransformer() {
		return new ClosureTransformer(function($input){
			return (is_array($input)) 
				? "Array(".count($input).")"
				: strval($input);
		});
	}

}

?>